package top.v5it.japi.ddd.example.gateway;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author zhanpu
 * @date 2023/11/17
 */
@Slf4j
public class RSAGatewayFilterFactory extends AbstractGatewayFilterFactory<RSAGatewayFilterFactory.Config> {

    private final ObjectMapper mapper = new ObjectMapper();

    public RSAGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            // 解密请求
            ServerHttpRequest decryptedRequest = decryptRequest(exchange.getRequest());

            // 转发解密后的请求给后端服务
            ServerWebExchange modifiedExchange = exchange.mutate().request(decryptedRequest).build();
            return chain.filter(modifiedExchange).then(Mono.fromRunnable(() -> {
                // 加密后端响应
                encryptResponse(modifiedExchange.getResponse());
            }));
        };
    }

    @Override
    public String name() {
        return "RSAGatewayFilterFactory";
    }

    private ServerHttpRequest decryptRequest(ServerHttpRequest request) {
        // 在此处实现RSA解密逻辑，并返回解密后的请求
        // ...
        boolean isDecrypt = false;
        final HttpHeaders headers = request.getHeaders();
        final List<String> list = headers.get(HttpHeaders.CONTENT_TYPE);
        if (Objects.isNull(list)) return request;
        for (String type : list) {
            if (MediaType.APPLICATION_JSON_VALUE.equals(type)) {
                isDecrypt = true;
                break;
            }
        }
        if (isDecrypt) {
            log.info("解密请求");
            final Flux<DataBuffer> body = request.getBody();

            body.doOnNext(t -> {
                final InputStream inputStream = t.asInputStream();
                try {
                    final Map<String, Object> map = mapper.readValue(inputStream, Map.class);
                    log.info("拦截请求体：{}", map);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }
        return request;
    }

    private void encryptResponse(ServerHttpResponse response) {
        // 在此处实现RSA加密逻辑，对后端响应进行加密
        // ...
    }

    public static class Config {
        // 可以添加一些配置属性，根据需要进行配置
    }
}
